
Comme nos 5 sens, les capteurs de téléphones peuvent donner des informations bien utiles pour certaines applications...
Ce tutorial utilise une approche code-behind où toute la logique de gestion des capteurs est directement dans le fichier XAML.CS.
Pour utiliser l'accéléromètre, il faut l'activer et assigner une fonction qui sera appelée en cas de changement des données du capteur (la fréquence d'actualisation est adaptable...)

Voici la structure XAML pour afficher les données de l'accéléromètre :
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="HelloMaui1.SensorPage"
Title="Sensors">
<VerticalStackLayout>
<Frame BorderColor="Red" Margin="5,5,5,0">
<StackLayout>
<Label x:Name="sensorValueLabel"
Text="Données du capteur: N/A"
VerticalOptions="Center"
HorizontalOptions="Center" />
<Button x:Name="enableButton"
Text="Activer / Désactiver l'accéléromètre"
Clicked="OnEnableClicked" />
<HorizontalStackLayout Margin="0,0,10,0">
<Label x:Name="enabledLabel" Text="on" IsVisible="False" />
<Label x:Name="disabledLabel" Text="off" IsVisible="True" />
</HorizontalStackLayout>
<BoxView x:Name="cancelIndicator"
Margin="0,10,0,0"
Color="Red"
HeightRequest="200"
WidthRequest="200" />
<HorizontalStackLayout Margin="0,15,0,0">
<Label x:Name="thresholdLabel" Text="Seuil: 0" />
<Slider x:Name="thresholdSlider"
Minimum="-10"
Maximum="10"
WidthRequest="150"
ValueChanged="OnThresholdChanged" />
</HorizontalStackLayout>
<Label x:Name="accelerationLabel"
Margin="0,30,0,0"
Text="Acceleration: 0" />
</StackLayout>
</Frame>
<Frame BorderColor="Green" Margin="5,10,5,0">
<StackLayout>
<Switch x:Name="shakeSwitch"
Toggled="OnShakeToggled" />
<BoxView x:Name="shakeIndicator"
Color="Black"
WidthRequest="150"
HeightRequest="150" />
</StackLayout>
</Frame>
</VerticalStackLayout>
</ContentPage>
Structure:
Voici l'implémentation complète dans le fichier XAML.CS:
using System.Diagnostics;
public partial class SensorPage : ContentPage
{
private string sensorValue;
private bool enabled = false;
private bool disabled = true;
// Variables pour la détection de seuil avancée
private bool cancel = false;
private string cancelColor = "Red";
private double threshold = 0;
private double acceleration = 0;
private Stopwatch stopwatch = new();
// Variables pour la détection de secousses
private string shakeColor = "Black";
public SensorPage()
{
InitializeComponent();
}
}
Ces variables permettent de:
sensorValue: Stocker les valeurs du capteurenabled/disabled: Suivre l'état du capteurthreshold: Valeur de seuil pour détecter une inclinaison maintenueacceleration: Valeur calculée de l'accélérationcancel/cancelColor: Gérer la détection d'une inclinaison prolongéestopwatch: Mesurer la durée d'une inclinaison au-delà du seuilprivate void OnEnableClicked(object sender, EventArgs e)
{
if (Accelerometer.Default.IsSupported)
{
if (!Accelerometer.Default.IsMonitoring)
{
// Activer l'accéléromètre
Accelerometer.Default.ReadingChanged += Accelerometer_ReadingChanged;
Accelerometer.Default.Start(SensorSpeed.Default);
enabled = true;
disabled = false;
// Mettre à jour l'UI
MainThread.BeginInvokeOnMainThread(() =>
{
enabledLabel.IsVisible = true;
disabledLabel.IsVisible = false;
});
}
else
{
// Désactiver l'accéléromètre
Accelerometer.Default.Stop();
Accelerometer.Default.ReadingChanged -= Accelerometer_ReadingChanged;
enabled = false;
disabled = true;
// Mettre à jour l'UI
MainThread.BeginInvokeOnMainThread(() =>
{
enabledLabel.IsVisible = false;
disabledLabel.IsVisible = true;
});
}
}
}
Points importants:
Accelerometer.Default.IsSupported: Vérifier si l'appareil a un accéléromètreIsMonitoring: Vérifier si le capteur est déjà actifReadingChanged += ...: S'abonner aux changements de valeursStart(SensorSpeed.Default): Démarrer la lecture du capteurprivate void OnThresholdChanged(object sender, ValueChangedEventArgs e)
{
threshold = e.NewValue;
MainThread.BeginInvokeOnMainThread(() =>
{
thresholdLabel.Text = $"Seuil: {threshold:F1}";
});
}
Ce slider permet de définir un seuil d'accélération. Si l'accélération dépasse ce seuil pendant 3 secondes, le BoxView rouge deviendra bleu.
private void Accelerometer_ReadingChanged(object sender, AccelerometerChangedEventArgs e)
{
// Récupérer les valeurs X, Y, Z
sensorValue = e.Reading.ToString();
// Calcul avancé: détecter une inclinaison maintenue sur l'axe Y
var data = e.Reading.Acceleration.Y;
acceleration = Math.Sqrt(data * data); // Valeur absolue via racine carrée
var thresholdPassed = acceleration >= threshold;
if (thresholdPassed)
{
if (!cancel)
{
// Premier dépassement du seuil: démarrer le chronomètre
stopwatch.Reset();
stopwatch.Start();
cancel = true;
}
else
{
// Seuil maintenu: vérifier si ça fait plus de 3 secondes
if (stopwatch.ElapsedMilliseconds > 3000)
{
cancelColor = "Blue"; // Seuil maintenu pendant 3 secondes!
stopwatch.Stop();
}
}
}
else
{
// Retour sous le seuil: réinitialiser
cancel = false;
cancelColor = "Red";
stopwatch.Stop();
}
// Mettre à jour l'UI (nécessaire sur le thread principal)
MainThread.BeginInvokeOnMainThread(() =>
{
sensorValueLabel.Text = $"Données du capteur: {sensorValue}";
accelerationLabel.Text = $"Acceleration: {acceleration:F2}";
cancelIndicator.Color = cancelColor == "Blue" ? Colors.Blue : Colors.Red;
});
}
Explication:
e.Reading contient les valeurs X, Y, Z de l'accélérationStopwatch: Permet de mesurer précisément le temps pendant lequel le seuil est dépasséMainThread.BeginInvokeOnMainThread(): Crucial car les événements du capteur arrivent sur un thread secondaireCas d'usage:
Cette logique pourrait servir à détecter une inclinaison prolongée du téléphone, par exemple pour annuler une action en maintenant le téléphone incliné pendant 3 secondes.
On peut stimuler l'accéléromètre en utilisant les outils avancés du simulateur:


Pour réagir à des secousses, il est nécessaire de faire un peu de calcul et définir un seuil de tolérance...
Tout cela est possible, néanmoins, MAUI intègre cela nativement et on peut donc réutiliser ce qui a déjà été implémenté...
La partie shake est déjà incluse dans le XAML complet ci-dessus (Frame vert):
Switch avec le gestionnaire OnShakeToggled pour activer/désactiver la détectionBoxView nommé "shakeIndicator" qui changera de couleur lors d'une secousseVoici l'implémentation complète de la détection de secousses (la variable shakeColor est déjà déclarée en haut):
private void OnShakeToggled(object sender, ToggledEventArgs e)
{
ToggleShake(e.Value);
}
Cette méthode est appelée quand l'utilisateur change l'état du switch. Avec l'approche code-behind, on utilise simplement l'événement Toggled standard du Switch.
private void ToggleShake(bool enable)
{
if (Accelerometer.Default.IsSupported)
{
if (enable)
{
// Activer la détection de secousses
Accelerometer.Default.ShakeDetected += Accelerometer_ShakeDetected;
Accelerometer.Default.Start(SensorSpeed.Default);
}
else
{
// Désactiver la détection
Accelerometer.Default.Stop();
Accelerometer.Default.ShakeDetected -= Accelerometer_ShakeDetected;
// Réinitialiser la couleur
shakeColor = "Black";
shakeIndicator.Color = Colors.Black;
}
}
}
Points importants:
ShakeDetected: Événement spécifique MAUI pour les secoussesprivate void Accelerometer_ShakeDetected(object sender, EventArgs e)
{
// Changer la couleur en rouge lors d'une secousse
shakeColor = "Red";
// Mettre à jour l'UI sur le thread principal
MainThread.BeginInvokeOnMainThread(() =>
{
shakeIndicator.Color = Colors.Red;
});
}
Explication:
MainThread.BeginInvokeOnMainThread() est nécessaire pour modifier l'UILe carré va donc changer de couleur lorsqu'une secousse est détectée.
Pour simuler une secousse avec l'émulateur, le plus simple est d'envoyer une commande:
adb emu sensor set acceleration 100:100:100 && timeout 1 > NUL && adb emu sensor set acceleration 0:0:0
Suite à cet exercice, les compétences suivantes ont été travaillées:
MainThread.BeginInvokeOnMainThread() pour mettre à jour l'UI depuis un thread secondaireReadingChanged et ShakeDetectedSwitch et Slider avec gestionnaires d'événementsStopwatch